
class Solution
{
public:
    vector<vector<int>> fourSum(vector<int> &nums, int target)
    {
        std::sort(nums.begin(), nums.end());

        std::vector<std::vector<int>> ret;
        int sz = nums.size();
        for (int i = 0; i < sz - 3; ++i)
        {
            if (i > 0 && nums[i - 1] == nums[i])
            {
                continue;
            }
            for (int j = i + 1; j < sz - 2; ++j)
            {
                if (j > (i + 1) && nums[j - 1] == nums[j])
                {
                    continue;
                }

                int left = j + 1, right = sz - 1;
                while (left < right)
                {
                    long long sum = (long long)nums[i] + nums[j] + nums[left] + nums[right];
                    if (sum < target)
                    {
                        ++left;
                    }
                    else if (sum > target)
                    {
                        --right;
                    }
                    else
                    {
                        ret.push_back({nums[i], nums[j], nums[left], nums[right]});
                        ++left;
                        --right;
                        while (left < right && nums[left - 1] == nums[left])
                        {
                            ++left;
                        }
                        while (left < right && nums[right + 1] == nums[right])
                        {
                            --right;
                        }
                    }
                }
            }
        }
        return ret;
    }
};

#include <vector>
#include <algorithm>

using namespace std;

class Solution
{
public:
    vector<vector<int>> fourSum(vector<int> &nums, int target)
    {
        sort(nums.begin(), nums.end());
        vector<vector<int>> result;
        int n = nums.size();

        for (int i = 0; i < n - 3; ++i)
        {
            if (i > 0 && nums[i] == nums[i - 1])
                continue;

            for (int j = i + 1; j < n - 2; ++j)
            {
                if (j > i + 1 && nums[j] == nums[j - 1])
                    continue;

                int left = j + 1;
                int right = n - 1;

                while (left < right)
                {
                    long long sum = (long long)nums[i] + nums[j] + nums[left] + nums[right];

                    if (sum < target)
                    {
                        ++left;
                    }
                    else if (sum > target)
                    {
                        --right;
                    }
                    else
                    {
                        result.push_back({nums[i], nums[j], nums[left], nums[right]});
                        ++left;
                        --right;

                        while (left < right && nums[left] == nums[left - 1])
                            ++left;
                        while (left < right && nums[right] == nums[right + 1])
                            --right;
                    }
                }
            }
        }

        return result;
    }
};

class Solution
{
public:
    vector<vector<int>> fourSum(vector<int> &nums, int target)
    {
        int sz = nums.size();
        vector<vector<int>> ans;
        if(sz < 4) return ans;

        sort(nums.begin(), nums.end()); // O(n*logn)

        for(int i = 0; i < sz - 3; ++i)
        {
            //optimization
            // if(nums[i] > target) break;
            //de-duplication
            if(i > 0 && nums[i] == nums[i-1]) continue;

            for(int j = i + 1; j < sz - 2; ++j)
            {
                //optimization
                // if(nums[i] + nums[j] > target) break;
                //de-duplication
                if(j > i + 1 && nums[j] == nums[j - 1]) continue;
                int left = j + 1, right = sz - 1;
                while(left < right)
                {
                    long long sum = (long long)nums[i] + nums[j] + nums[left] + nums[right];
                    if(sum == target){
                        ans.push_back({nums[i], nums[j], nums[left], nums[right]});
                        //de-duplication
                        while(left < right && nums[left] == nums[left + 1]) ++left;
                        while(left < right && nums[right] == nums[right - 1]) --right;
                        ++left;
                        --right;
                    }
                    else if(sum < target) ++left;
                    else --right;
                }
                
            }
        }
        return ans;
    }
};